﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Runtime.InteropServices;

namespace Rookey.Frame.IMClient
{
	public partial class Window : CustomForm
	{
		public Window()
		{
			InitializeComponent();
			browser1.Bounds = new Rectangle(BorderWidth, BorderWidth + TitleHeight, Width - BorderWidth * 2, Height - BorderWidth * 2 - TitleHeight);
			browser1.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
			_IWindow = new IWindowImpl(this);
			Icon = Properties.Resources.Tray;
		}

		object _config;
		object _OnClose = null;
		bool _isLoad = false;
		object _tag = null;

		public void Init(object config)
		{
			_config = config;

			_OnClose = Utility.GetProperty(config, "OnClose");

			_tag = Utility.GetProperty(config, "Tag");

			object title = Utility.GetProperty(config, "Title");

			Init(
				(int)Utility.GetProperty(config, "Left"),
				(int)Utility.GetProperty(config, "Top"),
				(int)Utility.GetProperty(config, "Width"),
				(int)Utility.GetProperty(config, "Height"),
				(int)Utility.GetProperty(config, "BorderWidth"),
				(int)Utility.GetProperty(title, "Height"),
				(bool)Utility.GetProperty(config, "Resizable"),
				(bool)Utility.GetProperty(config, "HasMinButton"),
				(bool)Utility.GetProperty(config, "HasMaxButton"),
				(int)Utility.GetProperty(config, "MinWidth"),
				(int)Utility.GetProperty(config, "MinHeight"),
				(string)Utility.GetProperty(title, "InnerHTML")
			);

			ShowInTaskbar = (bool)Utility.GetProperty(config, "ShowInTaskbar");

			browser1.Bounds = new Rectangle(BorderWidth, BorderWidth + TitleHeight, Width - BorderWidth * 2, Height - BorderWidth * 2 - TitleHeight);
			browser1.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;

			loadingTip1.Left = BorderWidth;
			loadingTip1.Width = Width - BorderWidth * 2;
			loadingTip1.Top = BorderWidth + TitleHeight;
			loadingTip1.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
			loadingTip1.BackColor = Color.FromArgb(0xFF, 0xFF, 0xDD);
			loadingTip1.Text = "正在加载...";
			loadingTip1.Visible = false;
		}

		IWindowImpl _IWindow = null;

		public IWindowImpl IWindow
		{
			get { return _IWindow; }
		}

		public class PageLoadEventArgs : EventArgs
		{
			public bool Result;
		}

		public delegate void PageLoadDelegate(object sender, PageLoadEventArgs e);

		public event PageLoadDelegate PageLoad;

		private void browser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
		{
			if (String.Compare(browser1.Url.LocalPath, e.Url.LocalPath) == 0)
			{
				_isLoad = true;
				IWindow.Completed();
				object result = browser1.Document.InvokeScript("SetClientMode", new object[] { true, IWindow });
				if (result != null && result.GetType() == typeof(Boolean) && (bool)result)
				{
					if (IWindow._onload_callback != null)
					{
						Utility.CallFunc(IWindow._onload_callback, IWindow);
					}
					_IWindow.OnLoad.Call(_IWindow);
				}

				PageLoadEventArgs args = new PageLoadEventArgs();
				args.Result = (result != null && result.GetType() == typeof(Boolean) && (bool)result);
				PageLoad(this, args);
			}
		}

		[DllImport("kernel32.dll")]
		private static extern bool SetProcessWorkingSetSize(
			IntPtr process,
			int minSize,
			int maxSize
		);

		protected override void OnClosed(EventArgs e)
		{
			if (Owner != null && !Owner.Enabled) Owner.Enabled = true;
			_IWindow.OnClosed.Call(_IWindow);
			base.OnClosed(e);

			GC.Collect();
			GC.WaitForPendingFinalizers();
			if (Environment.OSVersion.Platform == PlatformID.Win32NT)
			{
				SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
			}
		}

		protected override void OnVisibleChanged(EventArgs e)
		{
			if (Visible == false)
			{
				IWindow.OnHidden.Call(IWindow);
			}
			base.OnVisibleChanged(e);
		}

		[System.Runtime.InteropServices.ComVisibleAttribute(true)]
		public class IWindowImpl
		{
			Window _window = null;

			public object _onload_callback = null;

			public IWindowImpl(Window b)
			{
				_window = b;
			}

			public void ShowDialog(object parent, string pos, int left, int top, bool relativeParent, object callback)
			{
				if (parent != null)
				{
					_window.Owner = (parent as IWindowImpl)._window;
					MoveEx(pos, left, top, relativeParent);
					(parent as IWindowImpl)._window.Enabled = false;
					_window.Show();
				}
				else
				{

					MoveEx(pos, left, top, relativeParent);
					_window.Show();
				}
			}

			private void WriteCookies(string url)
			{
				string cookie = SessionImpl.Global.GetCookie();
				if (cookie != "")
				{
					string[] pairs = cookie.Split(new char[] { ';' });
					foreach (string p in pairs)
					{
						string[] ps = p.Split(new char[] { '=' });
						if (ps.Length == 2)
						{
							InternetSetCookie(url, ps[0], ps[1]);
						}
					}
				}
			}

			[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
			static extern bool InternetSetCookie(string lpszUrl, string lpszCookieName, string lpszCookieData);

			public void Load(String url, object onload)
			{
				_onload_callback = onload;

				if (url.StartsWith("http://", StringComparison.CurrentCultureIgnoreCase))
				{
                    WriteCookies(url);
					_window.browser1.Url = new Uri(url);
				}
				else
                {
                    WriteCookies(Global.ServiceUrl + "/" + url);
					_window.browser1.Url = new Uri(Global.ServiceUrl + "/" + url);
				}
			}

			[System.Runtime.InteropServices.DllImport("user32.dll")]
			static extern Int32 ShowWindow(IntPtr handle, Int32 nCmdWindow);

			[System.Runtime.InteropServices.DllImport("user32.dll ")]
			static extern bool SetForegroundWindow(IntPtr hWnd);

			public void Show()
			{
				ShowWindow(_window.Handle, 1);
				SetForegroundWindow(_window.Handle);
				_window.Refresh();
			}

			public void Hide()
			{
				_window.Hide();
			}

			public void Minimum()
			{
				_window.WindowState = FormWindowState.Minimized;
			}

			public void Close()
			{
				_window.Close();
			}

			public object GetTag()
			{
				return _window._tag;
			}

			public void SetTag(object tag)
			{
				_window._tag = tag;
			}

			int _waitingCount = 0;

			public void Waiting(string text)
			{
				_waitingCount++;
				_window.loadingTip1.Text = String.IsNullOrEmpty(text) ? "正在加载..." : text;
				if (_waitingCount > 0) _window.loadingTip1.Visible = true;
			}

			public void Completed()
			{
				_waitingCount--;
				if (_waitingCount <= 0)
				{
					_window.loadingTip1.Visible = false;
					_waitingCount = 0;
				}
			}


			public void Move(int left, int top)
			{
				_window.Left = left;
				_window.Top = top;
			}

			public void MoveEx(string pos, int x, int y, bool relativeParent)
			{
				pos=pos.ToUpper();
				if (pos == "") pos = "LEFT|TOP";
				else if (pos == "CENTER") pos = "MIDDLE|MIDDLE";

				string[] poss = pos.Split(new char[] { '|' });

				Rectangle rect=Rectangle.Empty;
				if (_window.Owner != null && relativeParent) rect = _window.Owner.Bounds;
				else rect = Screen.PrimaryScreen.WorkingArea;

				int left;
				if (poss[0] == "LEFT") left = rect.Left;
				else if (poss[0] == "RIGHT") left = rect.Right - GetWidth();
				else left = rect.Left + (rect.Width - GetWidth()) / 2;
				left += x;

				int top;
				if (poss[1] == "TOP") top = rect.Top;
				else if (poss[1] == "BOTTOM") top = rect.Bottom - GetHeight();
				else top = rect.Top + (rect.Height - GetHeight()) / 2;
				top += y;

				Move(left, top);
			}

			public void Resize(int width, int height)
			{
				_window.Width = width;
				_window.Height = height;
			}

			public object GetHtmlWindow()
			{
				return _window.browser1.Document != null ? _window.browser1.Document.Window.DomWindow : null;
			}

			CommonEvent _OnLoad = new CommonEvent();
			CommonEvent _OnHidden = new CommonEvent();
			CommonEvent _OnClosed = new CommonEvent();
			NotifyEvent _OnNotify = new NotifyEvent();

			public CommonEvent OnLoad
			{
				get { return _OnLoad; }
			}

			public CommonEvent OnHidden
			{
				get { return _OnHidden; }
			}

			public CommonEvent OnClosed
			{
				get { return _OnClosed; }
			}

			public NotifyEvent OnNotify
			{
				get { return _OnNotify; }
			}

			public bool IsLoad()
			{
				return _window._isLoad;
			}

			public void SetTitle(string title)
			{
				_window.Text = title;
				_window.m_LabelText.Text = title;
			}

			public String GetTitle()
			{
				return _window.Text;
			}

			public bool IsVisible()
			{
				return _window.Visible;
			}

			public bool IsTop()
			{
				return _window.Visible;
			}

			public void BringToTop()
			{
				ShowWindow(_window.Handle, 1);
				SetForegroundWindow(_window.Handle);
				_window.Refresh();
			}

			public int GetWidth()
			{
				if (_window.WindowState == FormWindowState.Minimized) return _window.RestoreBounds.Width;
				else return _window.Width;
			}

			public int GetHeight()
			{
				if (_window.WindowState == FormWindowState.Minimized) return _window.RestoreBounds.Height;
				else return _window.Height;
			}

			public int GetClientWidth()
			{
				return GetWidth() - _window._borderWidth * 2;
			}

			public int GetClientHeight()
			{
				return GetHeight() - _window.BorderWidth * 2 - _window.TitleHeight;
			}

			[DllImport("user32.dll")]
			static extern Int32 FlashWindowEx(ref FLASHWINFO pwfi);

			[StructLayout(LayoutKind.Sequential)]
			public struct FLASHWINFO
			{
				public UInt32 cbSize;
				public IntPtr hwnd;
				public Int32 dwFlags;
				public UInt32 uCount;
				public Int32 dwTimeout;
			}

			public void Notify()
			{
				ShowWindow(_window.Handle, 5);

				FLASHWINFO fw = new FLASHWINFO();
				fw.cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(FLASHWINFO)));
				fw.hwnd = _window.Handle;
				fw.dwFlags = 2;
				fw.uCount = 4;
				fw.dwTimeout = 400;
				FlashWindowEx(ref fw);
			}
		}

		private void Window_FormClosed(object sender, FormClosedEventArgs e)
		{
			IWindow.OnClosed.Call(IWindow);
		}

		private void Window_FormClosing(object sender, FormClosingEventArgs e)
		{
		}

		private void m_BtnClose_Click(object sender, EventArgs e)
		{
			if (_OnClose != null && _OnClose != DBNull.Value)
			{
				Utility.CallFunc(_OnClose, IWindow);
			}
			else
			{
				Close();
			}

		}
	}

	[System.Runtime.InteropServices.ComVisibleAttribute(true)]
	public class CommonEvent : Delegate
	{
		public void Call(object val)
		{
			base.CallAll(val);
		}
	}

	[System.Runtime.InteropServices.ComVisibleAttribute(true)]
	public class NotifyEvent : Delegate
	{
		public void Call(string command, object data)
		{
			base.CallAll(command, data);
		}
	}
}
